package com.rengwuxian.coursecoroutines._1_basics

import android.os.Bundle
import android.widget.TextView
import androidx.activity.ComponentActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import com.rengwuxian.coursecoroutines.R
import com.rengwuxian.coursecoroutines.common.Contributor
import com.rengwuxian.coursecoroutines.common.gitHub
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit

/**
 * 自动切回来：挂起函数
 * suspend、挂起函数 vs 回调、挂起函数 vs 协程
 *
 * 传统写法：
 *   Retrofit ： Call 回调形式：在后台线程进行网络请求，完成后，再切回主线程回调方法。
 * 协程写法：
 *   private fun coroutinesStyle() = CoroutineScope(Dispatchers.Main).launch {
 *     val contributors = gitHub.contributors("square", "retrofit")
 *     showContributors(contributors)
 *   }
 * 上下两行代码发生在不同的线程，gitHub.contributors("square", "retrofit") 发生在后台线程，返回后，
 * val contributors = 赋值操作和showContributors(contributors) 发生在主线程。
 * 全靠一个关键字：suspend 暂停 -》执行这个函数时，所在的协程会被挂起，是只不会再占用这个线程的资源，会把所在的线程资源让出。
 * 核心点：协程和当前线程的暂时脱离，当前线程被让出了，且真正的挂起函数被切到它所在的线程进行网络请求了。完成后，resume，恢复原来的线程or线程池。
 * 也说明：挂起函数只有在协程中使用才有意义。
 *
 * 很多三方的开源库都支持协程了，定义了suspend函数。retrofit、room等。有特定的业务。
 *
 */
class SuspendActivity : ComponentActivity() {
  private lateinit var infoTextView: TextView

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.layout_1)
    infoTextView = findViewById(R.id.infoTextView)


//    callbackStyle()
    coroutinesStyle()
  }

  private fun callbackStyle() {
    gitHub.contributorsCall("square", "retrofit")
      .enqueue(object : Callback<List<Contributor>> {
        override fun onResponse(
          call: Call<List<Contributor>>, response: Response<List<Contributor>>,
        ) {
          showContributors(response.body()!!)
          gitHub.contributorsCall("square", "okhttp")
            .enqueue(object : Callback<List<Contributor>> {
              override fun onResponse(
                call: Call<List<Contributor>>, response: Response<List<Contributor>>,
              ) {
                showContributors(response.body()!!)
              }

              override fun onFailure(call: Call<List<Contributor>>, t: Throwable) {
                t.printStackTrace()
              }
            })
        }

        override fun onFailure(call: Call<List<Contributor>>, t: Throwable) {
          t.printStackTrace()
        }
      })
  }

  private fun coroutinesStyle() = CoroutineScope(Dispatchers.Main).launch {
    val contributors = gitHub.contributors("square", "retrofit")
    showContributors(contributors)
    val contributors2 = gitHub.contributors("square", "okhttp")
    showContributors(contributors2)
  }

  private fun coroutine111() = CoroutineScope(Dispatchers.Main).launch {
      val contributors = gitHub.contributors("square", "retrofit")
      showContributors(contributors)
  }

  private fun showContributors(contributors: List<Contributor>) = contributors
    .map { "${it.login} (${it.contributions})" }
    .reduce { acc, s -> "$acc\n$s" }
    .let { infoTextView.text = it }
}